/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.v2.common.om;

/**
 * Represents the content of a source or target. This is the collection of all fragments for the
 * content (segments and non-segments).
 */
public interface ITextContainer extends Iterable<ITextFragment> {

	/**
	 * Indicates if this container is empty (no text and no codes).
	 * @return true if this container is empty.
	 */
	public boolean isEmpty ();
	
	/**
	 * Gets the number of fragments (segments and non-segments) in this container.
	 * This method always returns at least 1 as there is always at least 1 segment in a container.
	 * @return the number of fragment (segments and non-segments) in this container.
	 */
	public int size ();

	/**
	 * Helper method equivalent to <code>appendSegment(true)</code>.
	 * @return a new segment or an existing one.
	 * @see #appendSegment(boolean)
	 */
	public ISegment appendSegment ();
	
	/**
	 * Creates a new segment at the end of this container or return an existing one.
	 * If the previous fragment is a segment, if it is empty and if usePreviousIfEmpty is set to true
	 * no new segment is create and the existing last segment is returned.
	 * In all other cases a new segment is created and returned.
	 * @param usePreviousIfEmpty true to re-use an existing segment (if it is empty and is the last
	 * fragment of this container), false to always create a new segment.
	 * @return a new segment or an existing one.
	 * @see #appendSegment()
	 */
	public ISegment appendSegment (boolean usePreviousIfEmpty);
	
	/**
	 * Creates a string representing the content of this container, including the original codes whenever
	 * possible. Annotations are not represented and hidden protected content is also not represented.
	 * @return the content of this container.
	 */
	public String getText ();
	
	/**
	 * Gets the collection of tags associated with this container.
	 * @return the collection of tags associated with this container (can be empty but never null).
	 */
	public ITags getTags ();

	/**
	 * Gets the part (segment or ignorable part) at a given part index.
	 * @param partIndex the index of the part to retrieve (between 0 and {@link #getPartCount()}-1).
	 * Note that the part index may not be the same as the segment index.
	 * @return the {@link ITextFragment} object at the given part index position.
	 * @throws IndexOutOfBoundsException if the index is invalid.
	 */
	public ITextFragment getPart (int partIndex);

	/**
	 * Gets the part (segment or ignorable part) for a given id.
	 * @param id the id to look for.
	 * @return the {@link ITextFragment} object with the given id or null if not found.
	 */
	public ITextFragment getPart (String id);
	
	/**
	 * Gets the segment part at a given segment index.
	 * <p><b>Important:</b> This method may be slower than calling {@link #getPart(int)} 
	 * when you know the part index for the given segment. 
	 * @param segIndex the segment index of the segment to retrieve (between 0 and the number of segments).
	 * Note that the segment index may not be the same as the part index.
	 * @return the {@link ISegment} object at the given segment index position.
	 * @throws IndexOutOfBoundsException if the index is invalid.
	 */
	public ISegment getSegment (int segIndex);
	
	/**
	 * Gets the segment for a given id.
	 * @param id the id to look for.
	 * @return the {@link ISegment} object with the given id or null if not found.
	 */
	public ISegment getSegment (String id);

}
